{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 作业(⼆) 手写数字识别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入Python库\n",
    "import numpy as np\n",
    "from collections import Counter\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 载入手写数字灰度图像样本，样本包含1797个手写数字灰度图像，每个图像大小为8*8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1797,)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#加载标签文件\n",
    "y = np.load('digits/digits_lable.npy')\n",
    "y.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#前10个标签\n",
    "y[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([9, 0, 8, 9, 8], dtype=int64)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#倒数5个标签\n",
    "y[-5:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1797, 64)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#加载图像文件\n",
    "X = np.load('digits/digits_images.npy')\n",
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],\n",
       "       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],\n",
       "       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],\n",
       "       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],\n",
       "       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],\n",
       "       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],\n",
       "       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., 12., 13.,  5.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., 11., 16.,  9.,  0.,  0.],\n",
       "       [ 0.,  0.,  3., 15., 16.,  6.,  0.,  0.],\n",
       "       [ 0.,  7., 15., 16., 16.,  2.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., 16., 16.,  3.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., 16., 16.,  6.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., 16., 16.,  6.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., 11., 16., 10.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  4., 15., 12.,  0.,  0.],\n",
       "       [ 0.,  0.,  3., 16., 15., 14.,  0.,  0.],\n",
       "       [ 0.,  0.,  8., 13.,  8., 16.,  0.,  0.],\n",
       "       [ 0.,  0.,  1.,  6., 15., 11.,  0.,  0.],\n",
       "       [ 0.,  1.,  8., 13., 15.,  1.,  0.,  0.],\n",
       "       [ 0.,  9., 16., 16.,  5.,  0.,  0.,  0.],\n",
       "       [ 0.,  3., 13., 16., 16., 11.,  5.,  0.],\n",
       "       [ 0.,  0.,  0.,  3., 11., 16.,  9.,  0.],\n",
       "       [ 0.,  0.,  7., 15., 13.,  1.,  0.,  0.],\n",
       "       [ 0.,  8., 13.,  6., 15.,  4.,  0.,  0.],\n",
       "       [ 0.,  2.,  1., 13., 13.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  2., 15., 11.,  1.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  1., 12., 12.,  1.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  1., 10.,  8.,  0.],\n",
       "       [ 0.,  0.,  8.,  4.,  5., 14.,  9.,  0.],\n",
       "       [ 0.,  0.,  7., 13., 13.,  9.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  1., 11.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  7.,  8.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., 13.,  6.,  2.,  2.,  0.],\n",
       "       [ 0.,  0.,  7., 15.,  0.,  9.,  8.,  0.],\n",
       "       [ 0.,  5., 16., 10.,  0., 16.,  6.,  0.],\n",
       "       [ 0.,  4., 15., 16., 13., 16.,  1.,  0.],\n",
       "       [ 0.,  0.,  0.,  3., 15., 10.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  2., 16.,  4.,  0.,  0.],\n",
       "       [ 0.,  0., 12., 10.,  0.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 14., 16., 16., 14.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 16., 15., 10.,  1.,  0.],\n",
       "       [ 0.,  0., 11., 16., 16.,  7.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.,  4.,  7., 16.,  7.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  4., 16.,  9.,  0.],\n",
       "       [ 0.,  0.,  5.,  4., 12., 16.,  4.,  0.],\n",
       "       [ 0.,  0.,  9., 16., 16., 10.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., 12., 13.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  5., 16.,  8.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 16.,  3.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 14., 13.,  0.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 15., 12.,  7.,  2.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 16., 13., 16.,  3.,  0.],\n",
       "       [ 0.,  0.,  7., 16., 11., 15.,  8.,  0.],\n",
       "       [ 0.,  0.,  1.,  9., 15., 11.,  3.,  0.],\n",
       "       [ 0.,  0.,  7.,  8., 13., 16., 15.,  1.],\n",
       "       [ 0.,  0.,  7.,  7.,  4., 11., 12.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  8., 13.,  1.,  0.],\n",
       "       [ 0.,  4.,  8.,  8., 15., 15.,  6.,  0.],\n",
       "       [ 0.,  2., 11., 15., 15.,  4.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., 16.,  5.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  9., 15.,  1.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 13.,  5.,  0.,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  9., 14.,  8.,  1.,  0.,  0.],\n",
       "       [ 0.,  0., 12., 14., 14., 12.,  0.,  0.],\n",
       "       [ 0.,  0.,  9., 10.,  0., 15.,  4.,  0.],\n",
       "       [ 0.,  0.,  3., 16., 12., 14.,  2.,  0.],\n",
       "       [ 0.,  0.,  4., 16., 16.,  2.,  0.,  0.],\n",
       "       [ 0.,  3., 16.,  8., 10., 13.,  2.,  0.],\n",
       "       [ 0.,  1., 15.,  1.,  3., 16.,  8.,  0.],\n",
       "       [ 0.,  0., 11., 16., 15., 11.,  1.,  0.],\n",
       "       [ 0.,  0., 11., 12.,  0.,  0.,  0.,  0.],\n",
       "       [ 0.,  2., 16., 16., 16., 13.,  0.,  0.],\n",
       "       [ 0.,  3., 16., 12., 10., 14.,  0.,  0.],\n",
       "       [ 0.,  1., 16.,  1., 12., 15.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 16.,  9., 15.,  2.,  0.],\n",
       "       [ 0.,  0.,  0.,  3.,  0.,  9., 11.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  9., 15.,  4.,  0.],\n",
       "       [ 0.,  0.,  9., 12., 13.,  3.,  0.,  0.]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#前10个图像文件转换为列数为8的矩阵\n",
    "X10 = X[:10].reshape(-1, 8)\n",
    "X10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 72x720 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#展示前10个数字图像\n",
    "plt.figure(figsize=(1,10))\n",
    "plt.imshow(X10, cmap='gray')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.,  0.,  4., 10., 13.,  6.,  0.,  0.],\n",
       "       [ 0.,  1., 16., 14., 12., 16.,  3.,  0.],\n",
       "       [ 0.,  4., 16.,  6.,  3., 16.,  4.,  0.],\n",
       "       [ 0.,  0., 12., 16., 16., 16.,  5.,  0.],\n",
       "       [ 0.,  0.,  0.,  4.,  4., 16.,  8.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  0., 15.,  5.,  0.],\n",
       "       [ 0.,  0.,  5.,  7.,  7., 16.,  4.,  0.],\n",
       "       [ 0.,  0.,  2., 14., 15.,  9.,  0.,  0.],\n",
       "       [ 0.,  0.,  6., 16., 13., 11.,  1.,  0.],\n",
       "       [ 0.,  0., 16., 15., 12., 16.,  1.,  0.],\n",
       "       [ 0.,  3., 16.,  7.,  0., 13.,  6.,  0.],\n",
       "       [ 0.,  4., 16.,  0.,  0., 10.,  8.,  0.],\n",
       "       [ 0.,  8., 16.,  0.,  0., 14.,  6.,  0.],\n",
       "       [ 0.,  5., 16.,  7.,  9., 16.,  5.,  0.],\n",
       "       [ 0.,  1., 15., 16., 16., 16.,  1.,  0.],\n",
       "       [ 0.,  0.,  6., 16., 14.,  6.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., 11., 15.,  1.,  0.,  0.],\n",
       "       [ 0.,  0., 13., 16.,  8.,  2.,  1.,  0.],\n",
       "       [ 0.,  0., 16., 15., 10., 16.,  5.,  0.],\n",
       "       [ 0.,  0.,  8., 16., 16.,  7.,  0.,  0.],\n",
       "       [ 0.,  0.,  9., 16., 16.,  4.,  0.,  0.],\n",
       "       [ 0.,  0., 16., 14., 16., 15.,  0.,  0.],\n",
       "       [ 0.,  0., 15., 15., 15., 16.,  0.,  0.],\n",
       "       [ 0.,  0.,  2.,  9., 13.,  6.,  0.,  0.],\n",
       "       [ 0.,  0.,  2., 10.,  7.,  0.,  0.,  0.],\n",
       "       [ 0.,  0., 14., 16., 16., 15.,  1.,  0.],\n",
       "       [ 0.,  4., 16.,  7.,  3., 16.,  7.,  0.],\n",
       "       [ 0.,  5., 16., 10.,  7., 16.,  4.,  0.],\n",
       "       [ 0.,  0.,  5., 14., 14., 16.,  4.,  0.],\n",
       "       [ 0.,  0.,  0.,  0.,  0., 16.,  2.,  0.],\n",
       "       [ 0.,  0.,  4.,  7.,  7., 16.,  2.,  0.],\n",
       "       [ 0.,  0.,  5., 12., 16., 12.,  0.,  0.],\n",
       "       [ 0.,  0., 10., 14.,  8.,  1.,  0.,  0.],\n",
       "       [ 0.,  2., 16., 14.,  6.,  1.,  0.,  0.],\n",
       "       [ 0.,  0., 15., 15.,  8., 15.,  0.,  0.],\n",
       "       [ 0.,  0.,  5., 16., 16., 10.,  0.,  0.],\n",
       "       [ 0.,  0., 12., 15., 15., 12.,  0.,  0.],\n",
       "       [ 0.,  4., 16.,  6.,  4., 16.,  6.,  0.],\n",
       "       [ 0.,  8., 16., 10.,  8., 16.,  8.,  0.],\n",
       "       [ 0.,  1.,  8., 12., 14., 12.,  1.,  0.]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#倒数5个图像文件转换为列数为8的矩阵\n",
    "X5 = X[-5:].reshape(-1, 8)\n",
    "X5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 72x720 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#展示倒数5个数字图像\n",
    "plt.figure(figsize=(1,10))\n",
    "plt.imshow(X5, cmap='gray')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第一次测试(test_size=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用留出法拆分训练集与测试集，留出10%作为测试集。训练KNN模型，搜索最佳超参数k和p的取值，提升识别准确度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1618, 64)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ML.metrics import train_test_split\n",
    "#将手写数字灰度图像数据集拆分为训练集与测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, seed=1)\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(179, 64)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 5, 0, 7, 1, 0, 6, 1, 5, 4, 9, 2, 7, 8, 4, 6, 9, 3, 7, 4, 7, 1,\n",
       "       8, 6, 0, 9, 6, 1, 3, 7, 5, 9, 8, 3, 2, 8, 8, 1, 1, 0, 7, 9, 0, 0,\n",
       "       8, 7, 2, 7, 4, 3, 4, 3, 4, 0, 4, 7, 0, 5, 5, 5, 2, 1, 7, 0, 5, 1,\n",
       "       8, 3, 3, 4, 0, 3, 7, 4, 3, 4, 2, 9, 7, 3, 2, 5, 3, 4, 1, 5, 5, 2,\n",
       "       5, 2, 2, 2, 2, 7, 0, 8, 1, 7, 4, 2, 3, 8, 2, 3, 3, 0, 2, 9, 9, 2,\n",
       "       3, 2, 8, 1, 1, 9, 1, 2, 0, 4, 8, 5, 4, 4, 7, 6, 7, 6, 6, 1, 7, 5,\n",
       "       6, 3, 8, 3, 7, 1, 8, 5, 3, 4, 7, 8, 5, 0, 6, 0, 6, 3, 7, 6, 5, 6,\n",
       "       2, 2, 2, 3, 0, 7, 6, 5, 6, 4, 1, 0, 6, 0, 6, 4, 0, 9, 3, 8, 1, 2,\n",
       "       3, 1, 9], dtype=int64)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ML.KNN import KNeighbourClassifier\n",
    "#构建kNN算法对象（使用默认参数k=5,p=2）\n",
    "knn_clf = KNeighbourClassifier()\n",
    "#通过训练样本集训练模型\n",
    "knn_clf.fit(X_train, y_train)\n",
    "#通过测试样本集预测样本分类\n",
    "y_predict = knn_clf.predict(X_test)\n",
    "y_predict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#直接计算kNN算法的预测准确率\n",
    "knn_clf.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def best_KNN_param(X_train, X_test, y_train, y_test, max_k=10, max_p=9):\n",
    "    '''#训练KNN模型，搜索最佳的超参数k和p，使得预测准确率最高'''\n",
    "    best_score = 0\n",
    "    best_k = 0\n",
    "    best_p = 0\n",
    "    \n",
    "    for k in range(1, max_k+1):\n",
    "        for p in range(1, max_p+1):\n",
    "            knn_clf = KNeighbourClassifier(k=k, p=p)    #构建kNN算法对象\n",
    "            knn_clf.fit(X_train, y_train)               #通过训练样本集训练模型\n",
    "            score = knn_clf.score(X_test, y_test)       #计算kNN算法的预测准确率\n",
    "            if score > best_score:                      #存储更优的超参数k,p\n",
    "                best_score = score\n",
    "                best_k = k\n",
    "                best_p = p\n",
    "            if best_score >= 1:                         #已经达到最优，提前终止循环\n",
    "                break\n",
    "\n",
    "        if best_score >= 1:                             #已经达到最优，提前终止循环\n",
    "            break\n",
    "\n",
    "    return best_k, best_p, best_score                   #返回最佳超参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最佳手写数字灰度图像识别kNN算法模型超参数：k=1, p=7, score=1.0\n"
     ]
    }
   ],
   "source": [
    "#搜索最佳的超参数k(1-10)和p(1-9)，使得预测准确率最高\n",
    "best_k, best_p, best_score = best_KNN_param(X_train, X_test, y_train, y_test)\n",
    "print(\"最佳手写数字灰度图像识别kNN算法模型超参数：k={}, p={}, score={}\".format(best_k, best_p, best_score))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 结论：留出10%作为测试集(test_size=0.1)，预测准确率都很高，在超参数k=1,p=7时，预测准确率最高，达100%。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第二次测试(test_size=0.2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用留出法拆分训练集与测试集，留出20%作为测试集。训练KNN模型，搜索最佳超参数k和p的取值，提升识别准确度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1438, 64)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#将手写数字灰度图像数据集拆分为训练集与测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, seed=1)\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(359, 64)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9944289693593314"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#构建kNN算法对象（使用默认参数k=5,p=2）\n",
    "knn_clf = KNeighbourClassifier()\n",
    "#通过训练样本集训练模型\n",
    "knn_clf.fit(X_train, y_train)\n",
    "#直接计算kNN算法的预测准确率\n",
    "knn_clf.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最佳手写数字灰度图像识别kNN算法模型超参数：k=6, p=4, score=1.0\n"
     ]
    }
   ],
   "source": [
    "#搜索最佳的超参数k(1-20)和p(1-9)，使得预测准确率最高\n",
    "best_k, best_p, best_score = best_KNN_param(X_train, X_test, y_train, y_test, max_k=20, max_p=9)\n",
    "print(\"最佳手写数字灰度图像识别kNN算法模型超参数：k={}, p={}, score={}\".format(best_k, best_p, best_score))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 结论：留出20%作为测试集(test_size=0.2)，在超参数k=6,p=4时，预测准确率最高，达100%。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第三次测试(test_size=0.25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用留出法拆分训练集与测试集，留出25%作为测试集。训练KNN模型，搜索最佳超参数k和p的取值，提升识别准确度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1348, 64)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#将手写数字灰度图像数据集拆分为训练集与测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, seed=1)\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(449, 64)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9933184855233853"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#构建kNN算法对象（使用默认参数k=5,p=2）\n",
    "knn_clf = KNeighbourClassifier()\n",
    "#通过训练样本集训练模型\n",
    "knn_clf.fit(X_train, y_train)\n",
    "#直接计算kNN算法的预测准确率\n",
    "knn_clf.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最佳手写数字灰度图像识别kNN算法模型超参数：k=3, p=4, score=0.9955456570155902\n"
     ]
    }
   ],
   "source": [
    "#搜索最佳的超参数k(1-20)和p(1-9)，使得预测准确率最高\n",
    "best_k, best_p, best_score = best_KNN_param(X_train, X_test, y_train, y_test, max_k=20, max_p=9)\n",
    "print(\"最佳手写数字灰度图像识别kNN算法模型超参数：k={}, p={}, score={}\".format(best_k, best_p, best_score))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 结论：留出25%作为测试集(test_size=0.25)，在超参数k=3,p=4时，预测准确率最高，达99.55%。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
